﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;

namespace MyConsoleApp.Code
{
    public class ListByExpressTreeDemo
    {
        //缓存属性名和设定方法的委托
        private Dictionary<string, Delegate> hash;

        public ListByExpressTreeDemo()
        {
            hash = new Dictionary<string, Delegate>();
        }

        public void SetAllProperty<T>(List<T> list, string propertyName, object propertyValue)
        {
            if (list == null || list.Count == 0) return;
            PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
            
            if (propertyInfo != null && propertyInfo.CanWrite)
            {
                if (!hash.ContainsKey(propertyName))
                {
                    //var func = (a, b) => a.set(b);
                    ParameterExpression invokeObjExpr = Expression.Parameter(typeof(T), "invokeObj");//a
                    ParameterExpression propValExpr = Expression.Parameter(propertyInfo.PropertyType, "propVal");//b
                    
                    MethodInfo methodInfo = propertyInfo.GetSetMethod();   //set method                 
                    MethodCallExpression setMethodExpr = Expression.Call(invokeObjExpr, methodInfo, propValExpr);//a.set(b)

                    var lexpr = Expression.Lambda(setMethodExpr, invokeObjExpr, propValExpr);
                    Delegate action = lexpr.Compile();
                    hash.Add(propertyName, action);
                }

                list.ForEach(item => hash[propertyName].DynamicInvoke(item, propertyValue ));
            }
        }

        public void DisposeListByExpressTreeDemo()
        {
            hash = null;
        }
    }
}
